﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CPPEI.Coolzon.ServiceProxy.DataServiceRef;
using Visifire.Charts;
using System.Windows.Media.Animation;
using CPPEI.Coolzon.Common;
using System.Windows;
using System.Windows.Media;
using Visifire.Commons;

namespace CPPEI.Coolzon.UI.DataPartLib
{
    public partial class DataChartBase : DataPart
    {
        protected Storyboard _animationStoryboard;
        /// <summary>
        /// 记录每个DataPoint的最终值，动画结束后给每个DataPoint赋值，并清除动画
        /// </summary>
        protected Dictionary<DataPoint, double> dicDataPoitList;

        public DataChartBase()
        {
            DataPointWidth = 5;
            LegendEnabled = false;

            SetDefaultDataResult();
        }
        protected override void OnInit(PartContext context)
        {
            base.OnInit(context);
            ApplyXProperty();
        }

        protected override void OnApplyXProperty()
        {
            base.OnApplyXProperty();
            Chart chart = GetChart();
            if (chart == null)
            {
                return;
            }
            chart.Background = XBackground==null? null : XBackground.Brush;
            chart.View3D = XIs3DMode;
            chart.AnimatedUpdate = false;
            chart.PlotArea = GetPlotArea();
            chart.Titles.Clear();
            chart.Titles.Add(GetTitle());
            if (DataPointWidth != null)
            {
                chart.DataPointWidth = DataPointWidth.Value;
            }
            if (NeedUpdateLayout && chart.IsLoaded)
            {
                NeedUpdateLayout = false;
                chart.UpdateLayout();
            }
        }
        protected override void OnDestory()
        {
            Chart chart = GetChart();
            chart.Series.Clear();

            if (_animationStoryboard != null)
            {
                _animationStoryboard.Stop();
                _animationStoryboard.Remove();
                _animationStoryboard = null;
            }
            base.OnDestory();
        }

        protected override void OnDataBinding(DataResult dataResult)
        {
            ClearAnimation();
            StopAnimation();
            _animationStoryboard = new Storyboard();
            _animationStoryboard.FillBehavior = FillBehavior.HoldEnd;
            _animationStoryboard.Completed += _animationStoryboard_Completed;

            Chart chart = GetChart();
            chart.Series.Clear();
            if (dicDataPoitList == null)
            {
                dicDataPoitList = new Dictionary<DataPoint, double>();
            }
            else
            {
                dicDataPoitList.Clear();
            }

            if (dataResult.DataSeries.Length > 0)
            {
                foreach (ServiceProxy.DataServiceRef.DataSeries dataSerie in DataResult.DataSeries)
                {
                    Visifire.Charts.DataSeries vfdataSeries = new Visifire.Charts.DataSeries();
                    if (LineThickness != null)
                    {
                        vfdataSeries.LineThickness = LineThickness;
                    }
                    vfdataSeries.RenderAs = GetRender(dataSerie.Id);
                    vfdataSeries.Name = dataSerie.Name;
                    vfdataSeries.LegendText = dataSerie.Name;
                    vfdataSeries.Bevel = DataSeriesBevel;
                    vfdataSeries.ShowInLegend = LegendEnabled;
                    vfdataSeries.StartAngle = Math.Abs(XStartAngle) % 360;
                    vfdataSeries.LegendMarkerType = MarkerTypes.Cross;

                    double animationInteval = (XDataAnimationDuration) / (double)dataSerie.DataItems.Length;
                    int totalItemCount = dataSerie.DataItems.Length;

                    for (int itemIndex = 0; itemIndex < totalItemCount; itemIndex++)
                    {
                        ServiceProxy.DataServiceRef.DataItem dataItem = dataSerie.DataItems[itemIndex];
                        DataPoint datapoint = null;
                        datapoint = new DataPoint();
                        datapoint.Name = dataItem.Name;
                        datapoint.LegendText = dataItem.Name;
                        datapoint.YValue = 0;
                        datapoint.ShowInLegend = LegendEnabled;
                        datapoint.LegendMarkerType = MarkerTypes.Square;
                        SetDataPoint(datapoint);
                        vfdataSeries.DataPoints.Add(datapoint);

                        double dItemValue = Convertor.ToDouble(dataItem.Value);
                        DoubleAnimation animation = new DoubleAnimation(datapoint.YValue, dItemValue, new Duration(TimeSpan.FromSeconds(animationInteval)));
                        dicDataPoitList.Add(datapoint, dItemValue);

                        animation.BeginTime = TimeSpan.FromSeconds((totalItemCount - itemIndex - 1) * animationInteval);
                        Storyboard.SetTarget(animation, datapoint);
                        Storyboard.SetTargetProperty(animation, new PropertyPath(DataPoint.YValueProperty));
                        _animationStoryboard.Children.Add(animation);
                    }
                    chart.Series.Add(vfdataSeries);
                }

                if (_animationStoryboard != null)
                {
                    _animationStoryboard.Begin();
                }
            }

            SetLegends(chart.Legends);

            ApplyChartColorPlate(chart, XColorPlate);
        }

        protected virtual void SetDefaultDataResult()
        {
            Random random = new Random();
            ServiceProxy.DataServiceRef.DataSeries[] series = new ServiceProxy.DataServiceRef.DataSeries[1];
            ServiceProxy.DataServiceRef.DataItem[] tmpItems = new ServiceProxy.DataServiceRef.DataItem[5];
            for (int i = 1; i <= 5; i++)
            {
                tmpItems[i - 1] = new ServiceProxy.DataServiceRef.DataItem();
                tmpItems[i - 1].Id = "data" + i;
                tmpItems[i - 1].Name = "data" + i;
                tmpItems[i - 1].Value = (random.NextDouble() * 250).ToString("F2");
            }
            series[0] = new ServiceProxy.DataServiceRef.DataSeries();
            series[0].DataItems = tmpItems;
            series[0].Id = "series1";
            series[0].Name = "series1";
            DataResult = new ServiceProxy.DataServiceRef.DataResult();
            DataResult.DataSeries = series;
        }

        /// <summary>
        /// 动画完成事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void _animationStoryboard_Completed(object sender, EventArgs e)
        {
            ClearAnimation();
            //给DataPoint赋最终值并清除动画
            if (dicDataPoitList != null && dicDataPoitList.Count > 0)
            {
                foreach (var item in dicDataPoitList)
                {
                    try
                    {
                        item.Key.YValue = item.Value;
                    }
                    catch (Exception ex)
                    {

                    }
                }
                dicDataPoitList.Clear();
            }
            StopAnimation();
        }

        /// <summary>
        /// 清理动画，清理故事版中每个动画的target，防止内存溢出
        /// </summary>
        protected void ClearAnimation()
        {
            if (_animationStoryboard != null)
            {
                foreach (Timeline tl in _animationStoryboard.Children)
                {
                    tl.ClearValue(Storyboard.TargetProperty);
                }
            }
        }
        protected void StopAnimation()
        {
            if (_animationStoryboard != null)
            {
                _animationStoryboard.Completed -= _animationStoryboard_Completed;
                _animationStoryboard.Stop();
                _animationStoryboard.Remove();
                _animationStoryboard = null;
            }
        }
        protected virtual Chart GetChart()
        {
            return null;
        }
        protected virtual RenderAs GetRender(string dataSeriesId)
        {
            return RenderAs.Column;
        }
    }
}
